/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "ola_cloud_common.h"
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include "cJSON.h"
#include "ola_log.h"
#include "ola_error.h"
#include "ola_def.h"
#include "ola_pal_network.h"
#include "ola_base_utils.h"
#include "ola_link.h"
#include "ola_cloud_def.h"

/*
 * 功能: 云端回应包检测
 * 参数：session，待检测session
 *       pkt，待检测的coap包
 * 返回: 0，成功
 *       非0，错误码
 */
int CloudResponseCoapCheck(const OlaCoapSession *session, const OlaCoapPacket *pkt)
{
    if ((session == NULL) || (pkt == NULL)) {
        OlaLogWarning("invalid param");
        return OLA_COM_ERR_INVALID_ARGUMENT;
    }
    int ret = OLA_OK;

    do {
        if (!OlaIsValidCloudSession(session)) {
            OlaLogWarning("invalid session");
            ret = OLA_LINK_ERR_INVALID_SESSION;
            break;
        }
        if (pkt->header.code != OLA_COAP_RESPONSE_CODE_CONTENT) {
            OlaLogWarning("coap response error[%u]", pkt->header.code);
            ret = OLA_ERROR;
            break;
        }
        if ((pkt->payload.data == NULL) || (pkt->payload.len == 0)) {
            OlaLogWarning("coap empty response");
            ret = OLA_ERROR;
            break;
        }
    } while (false);

    return ret;
}

/*
 * 功能: 云端回应errcode统一处理接口
 * 参数：payload，云端返回的数据
 * 返回: 0，errcode正常
 *       非0，errcode有异常
 */
int CloudResponseErrcodeHandler(const OlaData *payload)
{
    if ((payload == NULL) || (payload->data == NULL)) {
        OlaLogWarning("invalid param");
        return OLA_COM_ERR_INVALID_ARGUMENT;
    }
    int ret;
    int errcode = CLOUD_ERRCODE_NO_ERROR;
    cJSON *json = NULL;

    do {
        json = cJSON_Parse((const char *)payload->data);
        if (json == NULL) {
            OlaLogError("json parse error");
            ret = OLA_CJSON_ERR_PARSE;
            break;
        }
        ret = OlaGetJsonNumber(json, OLA_STRING_ERRCODE, &errcode);
        if (ret != OLA_OK) {
            OlaLogError("get errcode error");
            ret = OLA_CJSON_ERR_PARSE;
            break;
        }
        if (errcode != CLOUD_ERRCODE_NO_ERROR) {
            /* errcode 统一处理 */
            OlaLogError("errcode=[%d]", errcode);
            ret = OLA_CLOUD_ERR_ERRCODE;
            break;
        }
    } while (false);

    cJSON_Delete(json);
    return ret;
}

/* 网络检测模块 */
static struct {
    unsigned long long lastTime; /* 网络监测最后一次时间 单位：ms */
    unsigned long long interval; /* 检测间隔 单位：ms */
} g_checkNetwork; /* 网络检测模块所有控制数据 */

/*
 * 功能: 网络检测模块初始化
 * 参数：interval，网络检测的间隔
 * 返回: 0，成功
 *       非0，错误码
 */
int CloudCheckNetworkInit(unsigned long long interval)
{
    int ret;

    g_checkNetwork.interval = interval;
    ret = OlaGetTime(&g_checkNetwork.lastTime);
    if (ret != OLA_OK) {
        OlaLogWarning("get time error");
    }

    return ret;
}

/*
 * 功能: 网络检测模块处理
 * 返回: 0，成功
 *       非0，错误码
 */
int CloudCheckNetworkProcess(void)
{
    int ret;
    bool isTimeout = false;
    int netState = 0; /* 0为初始值 */

    do {
        ret = OlaIsOvertime(&isTimeout, g_checkNetwork.lastTime, g_checkNetwork.interval);
        if (ret != OLA_OK) {
            OlaLogWarning("is overtime error");
            break;
        }
        if (isTimeout) {
            ret = OlaGetNetworkState(&netState);
            /* 0为接口执行状态，1位网络状态 */
            if ((ret != 0) || (netState != 1)) {
                OlaLogError("network error");
                break;
            }
            ret = OlaGetTime(&g_checkNetwork.lastTime);
            if (ret != OLA_OK) {
                OlaLogWarning("get time error");
                break;
            }
        }
    } while (false);

    return ret;
}